#include "ipcGetData.h"


static const char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int Base64encode(char *encoded, const char *string, int len);
static int SendData(const int nSocket, const char *pData, const int nSize, const int nTimeOut);
static void sendRD(int sock, int port, CameraInfo *pCameraInfo, int x);
static int Request(CameraInfo *pCameraInfo);
static int GetSession(CameraInfo *pCameraInfo);
static int GetPort(CameraInfo *pCameraInfo);
static int GetFrameRate(CameraInfo *pCameraInfo);
static int GetTrack(CameraInfo *pCameraInfo, const char *pTrackType);
static int Sending_And_Receiving(CameraInfo *pCameraInfo);
static int GetData(CameraInfo *pCameraInfo, int Seq);
static inline int initBlock(BlockInfo *pBlock);
static inline int udpBindPort(const int port);
static inline int getContinuePort(int *sock1, int *sock2, int *port1, int *port2, const int startPort, const int endPort);
static void HandleData(unsigned char *pData, const int iSize, void *arg);
static void* ConnectCameraThread(void* arg);
static void* dealThread(void *arg);
static inline int cameraLoop(void *arg);
static int connectTo(char *ip, int port, int nTimeOut);
static int RevData(int nSocket, char *pData, const int nSize, const int nTimeOut);


int initCamera(CameraInfo *pCameraInfo)
{
	if (getContinuePort(&(pCameraInfo->iRtpSock), &(pCameraInfo->iRtcpSock), &(pCameraInfo->iRtpPort), &(pCameraInfo->iRtcpPort), cameraClientUdpMinPort, cameraClientUdpMaxPort))
	{
		udi_erro_log("%s:getContinuePort fail !\n", __FUNCTION__);
		return -1;
	}

	if (initBlock(&(pCameraInfo->codeBlockInfo)))
	{
		udi_erro_log("initBlock fail !\n");
		return -2;
	}

	if (create_thread_small(&pCameraInfo->connect_thread_id, ConnectCameraThread, (void *)pCameraInfo))
	//if(pthread_create(&pCameraInfo->connect_thread_id, NULL, ConnectCameraThread, (void *)pCameraInfo))
	{
		udi_erro_log("create_thread_normal ConnectCameraThread fail !\n");
		return -3;
	}

	if (create_thread_small(&pCameraInfo->deal_thread_id, dealThread, (void *)pCameraInfo))
	//if(pthread_create(&pCameraInfo->deal_thread_id, NULL, dealThread, (void *)pCameraInfo))
	{
		udi_erro_log("create_thread_normal dealThread fail !\n");
		return -4;
	}

	return 0;
}

static void* dealThread(void *arg)
{
	CameraInfo *pCameraInfo = (CameraInfo *)arg;
	PopBlockInfoDataExNotConst(&(pCameraInfo->codeBlockInfo), HandleData, arg, cameraLoop, getBlockDataTimeInterval_S);

	return NULL;
}

static inline int cameraLoop(void *arg)
{
	CameraInfo *pCameraInfo = (CameraInfo *)arg;
	return (int)(pCameraInfo && pCameraInfo->is_start);
}

static void HandleData(unsigned char *pData, const int iSize, void *arg)
{
	CameraInfo *pCameraInfo = (CameraInfo *)arg;
	if (iSize < 14) return;

	unsigned char type;
	unsigned char start_bit;
	unsigned char end_bit;
	unsigned char start_sequence[] = { 0, 0, 0, 1 };

	type = (pData[12] & 0x1F);
	//if (type > 1 && type <= 23)
	//{
	//	//udi_erro_log("%s:type single ! %u, set it to 1 !\n", __FUNCTION__, type);
	//	type = 1;
	//}

	//if (type == 1)
	if (type >= 1 && type <= 23)
	{
		if ((pCameraInfo->iDataSize + iSize - 12 + 4) >= maxCodeSize)
		{
			udi_erro_log("%s:Length is too large !\n", __FUNCTION__);
			pCameraInfo->iDataSize = 0;
		}

		if (pCameraInfo->iDataSize == 0)
		{
			pCameraInfo->sequenceIndex2 = ((0x00ff & pData[2]) << 8) | (0x00ff & pData[3]);
			if (pCameraInfo->sequenceIndex2 == (pCameraInfo->sequenceIndex1 + 1))
			{
				pCameraInfo->timestamp2 = ((0x00ff & pData[4]) << 24) | ((0x00ff & pData[5]) << 16) | ((0x00ff & pData[6]) << 8) | (0x00ff & pData[7]);
				if (pCameraInfo->uiIncrementTimestamp <= 0) pCameraInfo->uiIncrementTimestamp = pCameraInfo->timestamp2 - pCameraInfo->timestamp1;
			}
		}

		memcpy(pCameraInfo->ucData1 + pCameraInfo->iDataSize, start_sequence, 4);
		memcpy(pCameraInfo->ucData1 + pCameraInfo->iDataSize + 4, pData + 12, iSize - 12);
		pCameraInfo->iDataSize += (iSize - 12 + 4);

		//if (type != 0x07 && type != 0x08 && type != 0x06)
		if(1)
		{
			pCameraInfo->sequenceIndex1 = ((0x00ff & pData[2]) << 8) | (0x00ff & pData[3]);
			pCameraInfo->timestamp1 = ((0x00ff & pData[4]) << 24) | ((0x00ff & pData[5]) << 16) | ((0x00ff & pData[6]) << 8) | (0x00ff & pData[7]);
			pCameraInfo->timestamp = pCameraInfo->timestamp1;
			//udi_info_log("1 set ts to %u, type = %u\n", pCameraInfo->timestamp, type);
			//udi_info_log("%s:before callback ! %p,%d,%u\n", __FUNCTION__, pCameraInfo->ucData1, pCameraInfo->iDataSize, pCameraInfo->timestamp);
			if(pCameraInfo->iDataSize > MAX_PERMIT_SIZE)
			{
				udi_erro_log("too big video package ! %u\n", pCameraInfo->iDataSize);
			}
			else 
			{
				pCameraInfo->pCallBack(pCameraInfo->ucData1, pCameraInfo->iDataSize, pCameraInfo->timestamp, pCameraInfo->channelndex, pCameraInfo->context);
			}

			pCameraInfo->iDataSize = 0;
		}
	}
	else if (type == 28)
	{
		start_bit = (0x80 & pData[13]);
		end_bit = (0x40 & pData[13]);
		pData[13] = (pData[13] & 0x1F) | (pData[12] & 0xE0);

		if (start_bit)
		{
			if ((pCameraInfo->iDataSize + iSize - 13 + 4) >= maxCodeSize)
			{
				udi_erro_log("%s:Length is too large !\n", __FUNCTION__);
				pCameraInfo->iDataSize = 0;
			}

			if (pCameraInfo->iDataSize == 0)
			{
				pCameraInfo->sequenceIndex2 = ((0x00ff & pData[2]) << 8) | (0x00ff & pData[3]);
				if (pCameraInfo->sequenceIndex2 == (pCameraInfo->sequenceIndex1 + 1))
				{
					pCameraInfo->timestamp2 = ((0x00ff & pData[4]) << 24) | ((0x00ff & pData[5]) << 16) | ((0x00ff & pData[6]) << 8) | (0x00ff & pData[7]);
					pCameraInfo->uiIncrementTimestamp = pCameraInfo->timestamp2 - pCameraInfo->timestamp1;
				}
			}

			memcpy(pCameraInfo->ucData1 + pCameraInfo->iDataSize, start_sequence, 4);
			memcpy(pCameraInfo->ucData1 + pCameraInfo->iDataSize + 4, pData + 13, iSize - 13);
			pCameraInfo->iDataSize += (iSize - 13 + 4);

		}
		else if (end_bit && (pCameraInfo->iDataSize > 0))
		{
			if ((pCameraInfo->iDataSize + iSize - 14) >= maxCodeSize)
			{
				udi_erro_log("%s:Length is too large !\n", __FUNCTION__);
				pCameraInfo->iDataSize = 0;
			}
			else
			{
				pCameraInfo->sequenceIndex1 = ((0x00ff & pData[2]) << 8) | (0x00ff & pData[3]);
				pCameraInfo->timestamp1 = ((0x00ff & pData[4]) << 24) | ((0x00ff & pData[5]) << 16) | ((0x00ff & pData[6]) << 8) | (0x00ff & pData[7]);
				memcpy(pCameraInfo->ucData1 + pCameraInfo->iDataSize, pData + 14, iSize - 14);
				pCameraInfo->timestamp = pCameraInfo->timestamp1;
				//udi_info_log("3 set ts to %u, type=%u\n", pCameraInfo->timestamp, type);
				pCameraInfo->iDataSize += (iSize - 14);
				if(pCameraInfo->iDataSize > MAX_PERMIT_SIZE)
				{
					udi_erro_log("too big video package ! %u\n", pCameraInfo->iDataSize);
				}
				else 
				{
					pCameraInfo->pCallBack(pCameraInfo->ucData1, pCameraInfo->iDataSize, pCameraInfo->timestamp, pCameraInfo->channelndex, pCameraInfo->context);
				}
				
				pCameraInfo->iDataSize = 0;
			}
		}
		else if (pCameraInfo->iDataSize > 0)
		{
			if ((pCameraInfo->iDataSize + iSize - 14) >= maxCodeSize)
			{
				udi_erro_log("Length is too large !\n");
				pCameraInfo->iDataSize = 0;
			}
			else
			{
				memcpy(pCameraInfo->ucData1 + pCameraInfo->iDataSize, pData + 14, iSize - 14);
				pCameraInfo->iDataSize += (iSize - 14);
			}
		}
		else
		{
			//udi_erro_log("No head !\n");
		}
	}
	else
	{
		pCameraInfo->iDataSize = 0;
	}
}

static void* ConnectCameraThread(void* arg)
{
	CameraInfo *pCameraInfo = (CameraInfo *)arg;
	Camera *pCamera = &(pCameraInfo->camera);

	while (pCameraInfo->is_start)
	{
		if (pCameraInfo->iTcpSock > 0)
		{
			close(pCameraInfo->iTcpSock);
			sleep(connectThreadSleepTime_S);
		}

		if ((pCameraInfo->iTcpSock = connectTo(pCamera->cIp, pCamera->iPort, tcpConnectWaitTime_S)) < 0)
		{
			//udi_erro_log("connect %s(%d) fail\n", pCamera->cIp, pCamera->iPort);
			sleep(connectThreadSleepTime_S);
			continue;
		}

		Request(pCameraInfo);

		close(pCameraInfo->iTcpSock);
		pCameraInfo->iTcpSock = -1;
		sleep(connectThreadSleepTime_S);
	}

	return NULL;
}

static inline int initBlock(BlockInfo *pBlock)
{
	return InitBlockInfoBuffer(pBlock, maxBlockBufNumber, blockSize, NULL, 0);
}

static inline int udpBindPort(const int port)
{
	return udpClientBindEx((unsigned short)port, udpSockSendBufSize, udpSockRecvBufSize);
}

static inline int getContinuePort(int *sock1, int *sock2, int *port1, int *port2, const int startPort, const int endPort)
{
	int port, s1, s2;
	for (port = startPort; port < endPort; port += 2)
	{
		s1 = udpBindPort(port);
		if (s1 <= 0)
		{
			//udi_info_log("udpBindPort fail ! port = %d, s1 = %d\n", port, s1);
			continue;
		}

		s2 = udpClientBind(port + 1);
		if (s2 <= 0)
		{
			//udi_info_log("udpBindPort fail ! port+1 = %d, s2 = %d\n", port + 1, s2);
			continue;
		}

		*sock1 = s1;
		*sock2 = s2;
		*port1 = port;
		*port2 = port + 1;

		return 0;
	}

	return -1;
}


static int Request(CameraInfo *pCameraInfo)
{
	int iSeq = 2;

	Camera *pCamera = &(pCameraInfo->camera);
	sprintf(pCameraInfo->cBuf1, "%s:%s", pCamera->cUsr, pCamera->cPassWd);
	Base64encode(pCameraInfo->cBuf2, pCameraInfo->cBuf1, strlen(pCameraInfo->cBuf1));
	sprintf(pCameraInfo->cBak1, "Authorization: Basic %s\r\n", pCameraInfo->cBuf2);

	//pCameraInfo->cBak1[0] = '\0';

	sprintf(pCameraInfo->cBuf1, "OPTIONS rtsp://%s:%d%s RTSP/1.0\r\n"
		"%s"
		"CSeq: %d\r\n"
		"User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Camera v2014.05.27)\r\n\r\n",
		pCamera->cIp, pCamera->iPort,
		(pCamera->cUrl[0] == '\0') ? "" : pCamera->cUrl,
		pCameraInfo->cBak1, iSeq++);

	if (Sending_And_Receiving(pCameraInfo) != 0) return -1;

	sprintf(pCameraInfo->cBuf1, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n"
		"%s"
		"CSeq: %d\r\n"
		"User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Camera v2014.05.27)\r\n\r\n",
		pCamera->cIp, pCamera->iPort,
		(pCamera->cUrl[0] == '\0') ? "" : pCamera->cUrl,
		pCameraInfo->cBak1, iSeq++);

	if (Sending_And_Receiving(pCameraInfo) != 0) return -2;

	if (GetTrack(pCameraInfo, "m=video") != 0)
	{
		//udi_erro_log("GetVideoTrack failed !\n");
		return -3;
	}

	//udi_info_log("GetTrack: %s\n", pCameraInfo->cTrackVideo);

	if (GetFrameRate(pCameraInfo) != 0)
	{
		//udi_erro_log("GetVideoTrack failed !\n");
		//return -3;
	}

	//udi_info_log("%s: %s:%s\n", __FUNCTION__, pCamera->cIp, pCameraInfo->cBuf2);

	sprintf(pCameraInfo->cBuf1, "SETUP rtsp://%s:%d%s/%s RTSP/1.0\r\n" \
		"%s" \
		"Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n" \
		"Blocksize: 1400\r\n" \
		"CSeq: %d\r\n" \
		"User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Camera v2014.05.27)\r\n\r\n",
		pCamera->cIp, pCamera->iPort,
		(pCamera->cUrl[0] == '\0') ? "" : pCamera->cUrl,
		pCameraInfo->cTrackVideo,
		pCameraInfo->cBak1,
		pCameraInfo->iRtpPort,
		pCameraInfo->iRtcpPort,
		iSeq++);

	if (Sending_And_Receiving(pCameraInfo) != 0) return -4;

	if (GetPort(pCameraInfo) != 0)
	{
		udi_erro_log("GetVideoPort failed !\n");
		return -5;
	}

	memset(pCameraInfo->cTmp1, 0x0, 12);
	sendRD(pCameraInfo->iRtpSock, pCameraInfo->iRemoteRtpPort, pCameraInfo, 0);
	memset(pCameraInfo->cTmp1, 0x0, 12);
	sendRD(pCameraInfo->iRtcpSock, pCameraInfo->iRemoteRtcpPort, pCameraInfo, 0);

	if (GetSession(pCameraInfo) != 0)
	{
		udi_erro_log("GetVideoSession failed !\n");
		return -6;
	}

	sprintf(pCameraInfo->cBuf1, "PLAY rtsp://%s:%d%s RTSP/1.0\r\n"
		"%s"
		"%s\r\n"
		"Range: npt=0.000-\r\n"
		"CSeq: %d\r\n"
		"User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Camera v2014.05.27)\r\n\r\n",
		pCamera->cIp, pCamera->iPort,
		(pCamera->cUrl[0] == '\0') ? "" : pCamera->cUrl,
		pCameraInfo->cBak1,
		pCameraInfo->cSession, iSeq++);

	if (Sending_And_Receiving(pCameraInfo) != 0) return -7;


	GetData(pCameraInfo, iSeq);

	return 0;
}


static int Sending_And_Receiving(CameraInfo *pCameraInfo)
{
	int   count, iDataLen, iLeaveLen;
	char *pTemp1;
	char *pTemp2;
	const char *pTmp3;

	//udi_info_log("SendData:%s\n", pCameraInfo->cBuf1);
	if (!SendData(pCameraInfo->iTcpSock, pCameraInfo->cBuf1, strlen(pCameraInfo->cBuf1), rtspSendWaitTime_S))
	{
		//udi_erro_log("%s:send fail !\n", __FUNCTION__);
		return -1;
	}

	if ((count = RevData(pCameraInfo->iTcpSock, pCameraInfo->cBuf2, recvDataLenEachTime, rtspRecvWaitTime_S)) <= 0)
	{
		//udi_erro_log("%s:recv fail !\n", __FUNCTION__);
		return -2;
	}

	//udi_info_log("RevData:%s\n", pCameraInfo->cBuf2);

	pCameraInfo->cBuf2[count] = '\0';

	if ((pTemp1 = strstr(pCameraInfo->cBuf2, "\r\n\r\n")) == NULL)
	{
		//udi_erro_log("%s:pCameraInfo->cBuf2 = %s!\n", __FUNCTION__, pCameraInfo->cBuf2);
		return -3;
	}

	iDataLen = count - (pTemp1 - pCameraInfo->cBuf2 + 4);
	pTmp3 = "Content-Length: ";

	if ((pTemp1 = strstr(pCameraInfo->cBuf2, pTmp3)) == NULL)
	{
		iLeaveLen = 0;
	}
	else
	{
		pTemp1 += strlen(pTmp3);
		if ((pTemp2 = strstr(pTemp1, "\r\n")) == NULL)
		{
			udi_erro_log("%s\n" ,pCameraInfo->cBuf2);
			return -4;
		}
		*pTemp2 = '\0';
		iLeaveLen = atoi(pTemp1) - iDataLen;
		*pTemp2 = '\r';
	}

	iDataLen = count;

	while ((iLeaveLen > 0) && ((iDataLen + iLeaveLen) < maxContentLen))
	{
		if ((count = RevData(pCameraInfo->iTcpSock, pCameraInfo->cBuf2 + iDataLen, iLeaveLen, rtspRecvWaitTime_S)) <= 0)
		{
			//udi_erro_log("%s:Receive failed\n", __FUNCTION__);
			return -5;
		}
		iLeaveLen -= count;
		iDataLen += count;
	}

	pCameraInfo->cBuf2[iDataLen] = '\0';

	//printf("%s\n",pCameraInfo->cBuf2);

	if (strstr(pCameraInfo->cBuf2, "RTSP/1.0 200 OK") != pCameraInfo->cBuf2)
	{
		//udi_erro_log("%s:pCameraInfo->cBuf2 = %s!\n", __FUNCTION__, pCameraInfo->cBuf2);
		return -6;
	}

	return 0;
}

static int GetTrack(CameraInfo *pCameraInfo, const char *pTrackType)
{
	char *pTmp1;
	char *pTmp2;
	const char *pTmp3 = pTrackType;

	if ((pTmp1 = strstr(pCameraInfo->cBuf2, pTmp3)) == NULL)
	{
		udi_erro_log("%s:no video 1!\n", __FUNCTION__);
		return -1;
	}

	pTmp3 = "a=control:";
	if ((pTmp2 = strstr(pTmp1, pTmp3)) == NULL)
	{
		udi_erro_log("%s:no video 2!\n", __FUNCTION__);
		return -2;
	}

	pTmp1 = pTmp2 + strlen(pTmp3);

	if ((pTmp2 = strstr(pTmp1, "\r\n")) == NULL)
	{
		udi_erro_log("%s:no video 3!\n", __FUNCTION__);
		return -3;
	}

	*pTmp2 = '\0';
	if (strlen(pTmp1) > 256)
	{
		udi_erro_log("Length is too large !\n");
		return -4;
	}
	strcpy(pCameraInfo->cTrackVideo, pTmp1);
	*pTmp2 = '\r';

	return 0;
}

static int GetFrameRate(CameraInfo *pCameraInfo)
{
	char *pTmp1;
	char *pTmp2;
	const char *pTmp3 = "a=framerate:";

	if ((pTmp1 = strstr(pCameraInfo->cBuf2, pTmp3)) == NULL)
	{
		//udi_erro_log("%s:no video !!\n", __FUNCTION__);
		return -1;
	}

	pTmp1 = pTmp1 + strlen(pTmp3);

	if ((pTmp2 = strstr(pTmp1, "\r\n")) == NULL)
	{
		udi_erro_log("%s:no video 2!\n", __FUNCTION__);
		return -3;
	}

	*pTmp2 = '\0';
	pCameraInfo->iFrameRate = atoi(pTmp1);
	*pTmp2 = '\r';

	return 0;
}

static int GetPort(CameraInfo *pCameraInfo)
{
	char *pTmp1;
	char *pTmp2;
	const char *pTmp3;

	pTmp3 = "server_port=";
	if ((pTmp1 = strstr(pCameraInfo->cBuf2, pTmp3)) == NULL)
	{
		udi_erro_log("%s:no server_port!\n", __FUNCTION__);
		return -1;
	}

	pTmp1 += strlen(pTmp3);

	pTmp3 = "-";
	if ((pTmp2 = strstr(pTmp1, pTmp3)) == NULL)
	{
		udi_erro_log("%s:no -!\n", __FUNCTION__);
		return -2;
	}

	*pTmp2 = '\0';
	pCameraInfo->iRemoteRtpPort = atoi(pTmp1);
	*pTmp2 = '-';

	pTmp1 = pTmp2 + 1;

	pTmp3 = ";";
	if ((pTmp2 = strstr(pTmp1, pTmp3)) == NULL)
	{
		pTmp3 = "\r";
		if ((pTmp2 = strstr(pTmp1, pTmp3)) == NULL)
		{
			udi_erro_log("%s:no r!\n", __FUNCTION__);
			return -3;
		}
	}

	if (*pTmp3 == ';')
	{
		*pTmp2 = '\0';
		pCameraInfo->iRemoteRtcpPort = atoi(pTmp1);
		*pTmp2 = ';';
	}
	else
	{
		*pTmp2 = '\0';
		pCameraInfo->iRemoteRtcpPort = atoi(pTmp1);
		*pTmp2 = '\r';
	}

	return 0;
}

static int GetSession(CameraInfo *pCameraInfo)
{
	char *pTmp1;
	char *pTmp2;
	char *pTmp4;
	const char *pTmp3;

	pTmp3 = "Session: ";
	if ((pTmp1 = strstr(pCameraInfo->cBuf2, pTmp3)) == NULL)
	{
		udi_erro_log("%s:no Session!\n", __FUNCTION__);
		return -1;
	}

	pTmp3 = ";";
	if ((pTmp2 = strstr(pTmp1, pTmp3)) == NULL)
	{
		pTmp3 = "\r";
		if ((pTmp2 = strstr(pTmp1, pTmp3)) == NULL)
		{
			udi_erro_log("%s:no :!\n", __FUNCTION__);
			return -2;
		}
	}
	else
	{
		*pTmp2 = '\0';
		pTmp3 = "\r";
		if ((pTmp4 = strstr(pTmp1, pTmp3)) != NULL)
		{
			*pTmp2 = ';';
			pTmp2 = pTmp4;
		}
		else
		{
			*pTmp2 = ';';
			pTmp3 = ";";
		}
	}

	if ((pTmp2 - pTmp1) > maxSessionLen)
	{
		udi_erro_log("%s: length too large ! \n", __FUNCTION__);
		return -3;
	}

	if (*pTmp3 == ';')
	{
		*pTmp2 = '\0';
		strcpy(pCameraInfo->cSession, pTmp1);
		*pTmp2 = ';';
	}
	else
	{
		*pTmp2 = '\0';
		strcpy(pCameraInfo->cSession, pTmp1);
		*pTmp2 = '\r';
	}

	return 0;
}


static void sendRD(int sock, int port, CameraInfo *pCameraInfo, int x)
{
	struct sockaddr_in clintaddr;
	socklen_t svrlen = sizeof(struct sockaddr_in);

	Camera *pCamera = &(pCameraInfo->camera);

	clintaddr.sin_family = AF_INET;
	clintaddr.sin_addr.s_addr = inet_addr(pCamera->cIp);
	clintaddr.sin_port = htons(port);

	if (pCameraInfo->cTmp1[0] == '\0')
	{
		pCameraInfo->cTmp1[0] = 0x80;
		pCameraInfo->cTmp1[1] = 0xc9;
		pCameraInfo->cTmp1[2] = 0x00;
		pCameraInfo->cTmp1[3] = 0x00;

		pCameraInfo->cTmp1[4] = 0x80;
		pCameraInfo->cTmp1[5] = 0xca;
		pCameraInfo->cTmp1[6] = 0x00;
		pCameraInfo->cTmp1[7] = 0x00;

		sendto(sock, pCameraInfo->cTmp1, 8, 0, (struct sockaddr*)&clintaddr, svrlen);
		return;
	}

	pCameraInfo->cTmp1[4] = (clintaddr.sin_addr.s_addr) >> 24;
	pCameraInfo->cTmp1[5] = (clintaddr.sin_addr.s_addr) >> 18;
	pCameraInfo->cTmp1[6] = (clintaddr.sin_addr.s_addr) >> 8;
	pCameraInfo->cTmp1[7] = ((clintaddr.sin_addr.s_addr) + x);

	pCameraInfo->cTmp1[12] = 0x00;
	pCameraInfo->cTmp1[13] = 0xff;
	pCameraInfo->cTmp1[14] = 0xff;
	pCameraInfo->cTmp1[15] = 0xff;

	pCameraInfo->cTmp1[16] = 0x00;
	pCameraInfo->cTmp1[17] = 0x01;

	pCameraInfo->cTmp1[18] = pCameraInfo->cTmp1[2];
	pCameraInfo->cTmp1[19] = pCameraInfo->cTmp1[3];

	pCameraInfo->cTmp1[20] = 0x00;
	pCameraInfo->cTmp1[21] = 0x00;
	pCameraInfo->cTmp1[22] = 0x00;
	pCameraInfo->cTmp1[23] = 0x00;

	memset(pCameraInfo->cTmp1 + 24, 0x0, 8);

	pCameraInfo->cTmp1[0] = 0x81;
	pCameraInfo->cTmp1[1] = 0xc9;
	pCameraInfo->cTmp1[2] = 0x00;
	pCameraInfo->cTmp1[3] = 0x07;

	pCameraInfo->cTmp1[32] = 0x81;
	pCameraInfo->cTmp1[33] = 0xca;
	pCameraInfo->cTmp1[34] = 0x00;
	pCameraInfo->cTmp1[35] = 0x04;

	pCameraInfo->cTmp1[36] = (clintaddr.sin_addr.s_addr) >> 24;
	pCameraInfo->cTmp1[37] = (clintaddr.sin_addr.s_addr) >> 18;
	pCameraInfo->cTmp1[38] = (clintaddr.sin_addr.s_addr) >> 8;
	pCameraInfo->cTmp1[39] = ((clintaddr.sin_addr.s_addr) + x);

	pCameraInfo->cTmp1[40] = 0x01;
	pCameraInfo->cTmp1[41] = 0x08;

	memcpy(pCameraInfo->cTmp1 + 42, "weiyiclt", 8);

	pCameraInfo->cTmp1[50] = 0x00;
	pCameraInfo->cTmp1[51] = 0x00;

	sendto(sock, pCameraInfo->cTmp1, 52, 0, (struct sockaddr*)&clintaddr, svrlen);
}

static int SendData(const int nSocket, const char *pData, const int nSize, const int nTimeOut)
{
	int ret, num;
	int nCount = 0;
	struct pollfd pollflag;

	do
	{
		pollflag.fd = nSocket;
		pollflag.events = POLLOUT;

		ret = poll(&pollflag, 1, nTimeOut * 1000);

		if (ret <= 0)
		{
			return ret;
		}

		num = (nSize - nCount) > 2096 ? 2096 : (nSize - nCount);

		ret = send(nSocket, pData + nCount, num, 0);

		if (ret <= 0)
		{
			return -2;
		}

		nCount += ret;
	} while (nCount < nSize);

	return nCount;
}

static int GetData(CameraInfo *pCameraInfo, int Seq)
{
	int ret, count;
	socklen_t svrlen;
	struct pollfd pollflag[3];
	struct sockaddr_in clintaddr;
	//char tmp[32];

	int iSeq = Seq;
	time_t tt, ttnow;
	time_t ttAudio;
	time(&tt);
	time(&ttAudio);

	Camera *pCamera = &(pCameraInfo->camera);

	while (cameraLoop((void *)pCameraInfo))
	{
		pollflag[0].fd = pCameraInfo->iTcpSock;
		pollflag[0].events = POLLIN;
		pollflag[0].revents = 0;

		pollflag[1].fd = pCameraInfo->iRtpSock;
		pollflag[1].events = POLLIN;
		pollflag[1].revents = 0;

		pollflag[2].fd = pCameraInfo->iRtcpSock;
		pollflag[2].events = POLLIN;
		pollflag[2].revents = 0;


		ret = poll(pollflag, 3, 5000);

		if (ret == 0)
		{
			udi_erro_log("Timeout !\n");
			break;
		}

		if (ret == -1)
		{
			udi_erro_log("Response error !\n");
			break;
		}

		if (pollflag[0].revents)
		{
			if ((count = RevData(pCameraInfo->iTcpSock, pCameraInfo->cBuf1, recvDataLenEachTime, 5)) <= 0)
			{
				udi_erro_log("Receive failed !\n");
				break;
			}
		}

		if (pollflag[1].revents)
		{
			svrlen = sizeof(clintaddr);
			count = recvfrom(pCameraInfo->iRtpSock, pCameraInfo->cBuf1, recvRtpDataLenEachTime, 0, (struct sockaddr*)&clintaddr, &svrlen);

			if (count <= 0)
			{
				udi_erro_log("Receive failed !\n");
				break;
			}

			if ((ret = pushBlock(&(pCameraInfo->codeBlockInfo), (unsigned char*)pCameraInfo->cBuf1, count)) != 0)
			{
				//udi_erro_log("M:%d", ret);
			}
			else
			{
				time(&ttnow);

				if ((ttnow - tt) > 10)
				{
					memcpy(pCameraInfo->cTmp1, pCameraInfo->cBuf1, count);

					sendRD(pCameraInfo->iRtcpSock, pCameraInfo->iRemoteRtcpPort, pCameraInfo, 0);

					tt = ttnow;

					sprintf(pCameraInfo->cTmp1, "OPTIONS rtsp://%s:%d%s RTSP/1.0\r\n"
						"%s"
						"CSeq: %d\r\n"
						"User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Camera v2014.05.27)\r\n\r\n",
						pCamera->cIp, pCamera->iPort,
						(pCamera->cUrl[0] == '\0') ? "" : pCamera->cUrl,
						pCameraInfo->cBak1,
						iSeq++);

					if (!SendData(pCameraInfo->iTcpSock, pCameraInfo->cTmp1, strlen(pCameraInfo->cTmp1), rtspSendWaitTime_S))
					{
						udi_erro_log("Send failed !\n");
						break;
					}
				}
			}
		}

		if (pollflag[2].revents)
		{
			svrlen = sizeof(clintaddr);
			count = recvfrom(pCameraInfo->iRtcpSock, pCameraInfo->cBuf1, recvDataLenEachTime, 0, (struct sockaddr*)&clintaddr, &svrlen);
		}
	}

	return 0;
}

static int connectTo(char *ip, int port, int nTimeOut)
{
	socklen_t             svrlen;
	struct sockaddr_in localaddr;
	int  sockls;
	int  ret, flag, error = 1;
	struct pollfd pollflag;

	svrlen = sizeof(localaddr);
	memset((char *)&localaddr, 0, svrlen);

	localaddr.sin_family = AF_INET;
	localaddr.sin_addr.s_addr = inet_addr(ip);
	localaddr.sin_port = htons(port);

	if ((sockls = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		//WriteLog(__FILE__,__LINE__,"socket error");
		return -1;
	}

	flag = fcntl(sockls, F_GETFL, 0);
	if (fcntl(sockls, F_SETFL, flag | O_NONBLOCK) == -1)
	{
		//WriteLog(__FILE__,__LINE__, "fcntl error");	
		close(sockls);
		return -2;
	}

	if (connect(sockls, (const struct sockaddr *)&localaddr, svrlen) != 0)
	{
		if (errno == EINPROGRESS)
		{
			pollflag.fd = sockls;
			pollflag.events = POLLOUT;

			ret = poll(&pollflag, 1, nTimeOut * 1000);

			if (ret <= 0)
			{
				close(sockls);
				return -3;
			}

			svrlen = sizeof(error);

			if (getsockopt(sockls, SOL_SOCKET, SO_ERROR, &error, &svrlen) == -1)
			{
				close(sockls);
				return -4;
			}

			if (error != 0)
			{
				close(sockls);
				return -5;
			}
		}
		else
		{
			close(sockls);
			return -6;
		}
	}

	return sockls;
}

static int RevData(int nSocket, char *pData, const int nSize, const int nTimeOut)
{
	int ret;
	struct pollfd pollflag;

	pollflag.fd = nSocket;
	pollflag.events = POLLIN;

	ret = poll(&pollflag, 1, nTimeOut * 1000);

	if (ret <= 0)
	{
		return ret;
	}

	ret = recv(nSocket, pData, nSize, 0);

	if (ret <= 0)
	{
		return -2;
	}

	return 	ret;
}

static int Base64encode(char *encoded, const char *string, int len)
{
	int i;
	char *p;

	p = encoded;
	for (i = 0; i < len - 2; i += 3) {
		*p++ = basis_64[(string[i] >> 2) & 0x3F];
		*p++ = basis_64[((string[i] & 0x3) << 4) |
			((int)(string[i + 1] & 0xF0) >> 4)];
		*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
			((int)(string[i + 2] & 0xC0) >> 6)];
		*p++ = basis_64[string[i + 2] & 0x3F];
	}
	if (i < len) {
		*p++ = basis_64[(string[i] >> 2) & 0x3F];
		if (i == (len - 1)) {
			*p++ = basis_64[((string[i] & 0x3) << 4)];
			*p++ = '=';
		}
		else {
			*p++ = basis_64[((string[i] & 0x3) << 4) |
				((int)(string[i + 1] & 0xF0) >> 4)];
			*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
		}
		*p++ = '=';
	}

	*p++ = '\0';
	return p - encoded;
}

